/**
 * Copyright 2022 Huawei Technologies Co., Ltd
 * <p>
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * <p>
 * http://www.apache.org/licenses/LICENSE-2.0
 * <p>
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.mindspore.vision.ui;

import android.app.Activity;
import android.content.Intent;
import android.content.SharedPreferences;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.os.Handler;
import android.preference.PreferenceManager;
import android.text.TextUtils;
import android.view.View;
import android.view.ViewStub;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.Toast;

import androidx.fragment.app.Fragment;
import androidx.viewpager.widget.ViewPager;

import com.bumptech.glide.Glide;
import com.google.android.material.tabs.TabLayout;
import com.mindspore.vision.R;
import com.mindspore.vision.base.BaseActivity;
import com.mindspore.vision.common.Constants;
import com.mindspore.vision.train.TrackingMobile;
import com.mindspore.vision.ui.adapter.BasePagerAdapter;
import com.mindspore.vision.ui.bean.ClassificationResultBean;
import com.mindspore.vision.ui.bean.ModelLabelBean;
import com.mindspore.vision.ui.help.ResultJsonHelper;
import com.mindspore.vision.ui.help.ResultTabHelper;
import com.mindspore.vision.utils.PathUtils;

import java.io.File;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import static com.mindspore.vision.common.Constants.TRANS_MODEL;

public class ResultActivity extends BaseActivity {

    private final static int DEALY_TIME = 500;
    private final static int REQUEST_FILE_PATH = 1;
    private final static String MS = "ms";
    private final static String JSON = "json";

    private int model;

    private Bitmap originClassificationBitmap;
    private ViewPager viewPager;
    private ClassificationChildFragment defaultFragment;
    private ClassificationChildFragment customFragment;

    private TrackingMobile commonTrackingMobile;
    private TrackingMobile customTrackingMobile;

    public static List<String> ModelTabList = new ArrayList<>();
    private File MS_FILE;
    private List<String> customLabelist;

    private List<Fragment> fragments;
    private BasePagerAdapter adapter;
    private SharedPreferences prefs;

    @Override
    public int getLayout() {
        return R.layout.activity_result;
    }

    protected void init() {
        model = getIntent().getIntExtra(TRANS_MODEL, 0);
        switch (model) {
            case Constants.TAG_CLASSIFICATION:
                prefs = PreferenceManager.getDefaultSharedPreferences(this);
                ViewStub classificationViewStub = findViewById(R.id.classificationLayout);
                View classificationView = classificationViewStub.inflate();
                ImageView imageView = classificationView.findViewById(R.id.img_result);
                String originPath = getIntent().getStringExtra(Constants.TRANS_ORIGIN);
                originClassificationBitmap = BitmapFactory.decodeFile(originPath);
                Glide.with(this).asBitmap().load(originClassificationBitmap).into(imageView);
                TabLayout mTabLayout = classificationView.findViewById(R.id.tab_layout);
                viewPager = classificationView.findViewById(R.id.viewPager);
                LinearLayout customLayout = classificationView.findViewById(R.id.custom_layout);
                customLayout.setOnClickListener(v -> {
                    Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
                    intent.setType("*/*");
                    intent.addCategory(Intent.CATEGORY_OPENABLE);
                    startActivityForResult(intent, REQUEST_FILE_PATH);
                });
                ModelTabList.add(getString(R.string.tab_common));
                initViewPager(mTabLayout);
                initTabLayout(mTabLayout);

                if (prefs.getBoolean(Constants.KEY_CLASSIFICATION_CUSTOM_STATE, false)) {
                    String customPath = prefs.getString(Constants.KEY_CLASSIFICATION_CUSTOM_PATH, "");
                    if (!TextUtils.isEmpty(customPath)) {
                        addCustomJsonFile(customPath);
                    } else {
                        prefs.edit().putBoolean(Constants.KEY_CLASSIFICATION_CUSTOM_STATE, false).apply();
                        Toast.makeText(this, R.string.custom_file_error, Toast.LENGTH_SHORT).show();
                    }
                }
                break;
            default:
                break;
        }
    }

    private void initClassificationModel(int position) {
        if (position == 0) {
            commonTrackingMobile = new TrackingMobile(this);
            boolean ret = commonTrackingMobile.loadModelFromBuf("mobilenetv2.ms", TrackingMobile.CLASSIFICATION_COMMON);
            if (!ret) {
                Toast.makeText(this, R.string.load_model_error, Toast.LENGTH_SHORT).show();
                return;
            }
            // run net.
            long startTime = System.currentTimeMillis();
            String result = commonTrackingMobile.MindSpore_runnet(originClassificationBitmap, 0);
            long endTime = System.currentTimeMillis();
            List<ClassificationResultBean> list = new ArrayList<>();

            String[] CONTENT_ARRAY = getResources().getStringArray(R.array.image_category);
            if (!TextUtils.isEmpty(result)) {
                String[] resultArray = result.split(";");
                for (String singleRecognitionResult : resultArray) {
                    String[] singleResult = singleRecognitionResult.split(":");
                    int nameIndex = Integer.parseInt(singleResult[0]);
                    float score = Float.parseFloat(singleResult[1]);
                    if (score > 0.5) {
                        list.add(new ClassificationResultBean(CONTENT_ARRAY[nameIndex], String.format("%.2f", (100 * score)) + "%", score));
                    }
                }
                Collections.sort(list, (t1, t2) -> Float.compare(t2.getScore(), t1.getScore()));
                String time = (endTime - startTime) + MS;
                list.add(new ClassificationResultBean(getString(R.string.inference_time), time));
                defaultFragment.setDataList(list);
            }
        } else {
            customTrackingMobile = new TrackingMobile(this);
            boolean ret = customTrackingMobile.loadModelFromBuf(MS_FILE.getPath(), TrackingMobile.CLASSIFICATION_CUSTOM);
            if (!ret) {
                Toast.makeText(this, R.string.load_model_error, Toast.LENGTH_SHORT).show();
                return;
            }
            // run net.
            long startTime = System.currentTimeMillis();
            String result = customTrackingMobile.MindSpore_runnet(originClassificationBitmap, customLabelist.size());
            long endTime = System.currentTimeMillis();

            List<ClassificationResultBean> list = new ArrayList<>();
            if (!TextUtils.isEmpty(result)) {
                String[] singleResult = result.split(":");
                int nameIndex = Integer.parseInt(singleResult[0]);
                float score = Float.parseFloat(singleResult[1]);
                list.add(new ClassificationResultBean(customLabelist.get(nameIndex), String.format("%.2f", (100 * score)) + "%", score));

                String time = (endTime - startTime) + MS;
                list.add(new ClassificationResultBean(getString(R.string.inference_time), time));
                customFragment.setDataList(list);
            }
        }
    }


    private void initTabLayout(TabLayout mTabLayout) {
        ResultTabHelper resultTabHelper = new ResultTabHelper(this, mTabLayout);
        resultTabHelper.initTabLayout(new ResultTabHelper.BaseOnTabSelectedListener() {
            @Override
            public void onTabSelected(TabLayout.Tab tab) {
                viewPager.setCurrentItem(tab.getPosition(), true);
                if (tab.getCustomView() != null) {
                    new Handler().postDelayed(() -> initClassificationModel(tab.getPosition()), DEALY_TIME);
                }
            }

            @Override
            public void onTabUnselected(TabLayout.Tab tab) {
                if (commonTrackingMobile != null) {
                    commonTrackingMobile.unloadCustomModel();
                }
                if (customTrackingMobile != null) {
                    customTrackingMobile.unloadCustomModel();
                }
            }

            @Override
            public void onTabReselected(TabLayout.Tab tab) {

            }
        });
    }

    private void initViewPager(TabLayout mTabLayout) {
        defaultFragment = ClassificationChildFragment.newInstance();

        fragments = new ArrayList<>();
        fragments.add(defaultFragment);

        adapter = new BasePagerAdapter(getSupportFragmentManager(), fragments);
        viewPager.setAdapter(adapter);
        viewPager.addOnPageChangeListener(new TabLayout.TabLayoutOnPageChangeListener(mTabLayout));
        viewPager.setOffscreenPageLimit(3);
        viewPager.setCurrentItem(0);
    }


    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (resultCode == Activity.RESULT_OK && requestCode == REQUEST_FILE_PATH) {
            if (data != null && data.getData() != null) {
                Uri uri = data.getData();
                String path = PathUtils.getFilePathByUri(ResultActivity.this, uri);
                if (!TextUtils.isEmpty(path)) {
                    addCustomJsonFile(path);
                } else {
                    prefs.edit().putBoolean(Constants.KEY_CLASSIFICATION_CUSTOM_STATE, false).apply();
                    Toast.makeText(this, R.string.custom_file_error, Toast.LENGTH_SHORT).show();
                }
            }
        }
    }

    public void addCustomJsonFile(String path) {
        File JSON_FILE = new File(path);
        if (JSON_FILE.exists() && path.toLowerCase().endsWith(JSON)) {
            ModelLabelBean bean = ResultJsonHelper.gonsAnalyzeJSON(JSON_FILE.getPath());
            if (!TextUtils.isEmpty(bean.getTitle()) && !TextUtils.isEmpty(bean.getFile())
                    && bean.getLabel() != null && bean.getLabel().size() > 0) {
                addCustomMSFile(bean, JSON_FILE);
            } else {
                prefs.edit().putBoolean(Constants.KEY_CLASSIFICATION_CUSTOM_STATE, false).apply();
                Toast.makeText(this,  R.string.custom_json_data_error, Toast.LENGTH_SHORT).show();
            }
        } else {
            prefs.edit().putBoolean(Constants.KEY_CLASSIFICATION_CUSTOM_STATE, false).apply();
            Toast.makeText(this, R.string.custom_json_file_error, Toast.LENGTH_SHORT).show();
        }
    }

    public void addCustomMSFile(ModelLabelBean bean, File JSON_FILE) {
        customLabelist = bean.getLabel();
        MS_FILE = new File(JSON_FILE.getParent(), bean.getFile());
        if (MS_FILE.exists() && MS_FILE.getPath().toLowerCase().endsWith(MS)) {
            prefs.edit().putBoolean(Constants.KEY_CLASSIFICATION_CUSTOM_STATE, true).apply();
            prefs.edit().putString(Constants.KEY_CLASSIFICATION_CUSTOM_PATH, JSON_FILE.getPath()).apply();
            ModelTabList.add(bean.getTitle());
            addNewCustom();
        } else {
            prefs.edit().putBoolean(Constants.KEY_CLASSIFICATION_CUSTOM_STATE, false).apply();
            Toast.makeText(this, R.string.custom_ms_file_error, Toast.LENGTH_SHORT).show();
        }
    }

    public void addNewCustom() {
        ResultTabHelper.addTabView();
        customFragment = ClassificationChildFragment.newInstance();
        fragments.add(customFragment);
        adapter.notifyDataSetChanged();
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        ModelTabList.clear();
    }
}


